package $2_1oo;

public class ExtendsFunction {

	public static void main(String[] args) {
		// 继承是面向对象编程中非常强大的一种机制，它首先可以复用代码。
		// Java使用extends关键字来实现继承

		Persons p = new Persons("小明", 12);
		Studenta s = new Studenta("小红", 20, 99);
		// TODO: 定义PrimaryStudent，从Student继承，新增grade字段:
		Studenta ps = new PrimaryStudent("小军", 9, 100, 5);
		System.out.println(ps.getScore());	// 100
	}
}

class Persons {
	// 继承有个特点，就是子类无法访问父类的private字段或者private方法。
	// 为了让子类可以访问父类的字段，我们需要把private改为protected。
	// 用protected修饰的字段可以被子类访问。
	protected String name;
	private int age;

	public Persons(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return this.name;
	}

	public int getAge() {
		return this.age;
	}

	public void setName(String name) {
		if (name == null || name.isBlank()) {
			throw new IllegalArgumentException("invalid name");
		}
		this.name = name.strip(); // 去掉首尾空格 // 前面的this不可少，少了就变成局部变量name了
	}

	public void setAge(int age) {
		if (age < 0 || age > 100) {
			throw new IllegalArgumentException("invalid age value");
		}
		this.age = age;
	}
}

class Student extends Persons {
	// super关键字表示父类（超类）。
	// 父类并没有无参数的构造方法，因此，调用父类错在的构造方法，使用super修饰符。
	public Student(String name, int age) {
		super(name, age);
	}

	// 不要重复name和age字段/方法,
	// 只需要定义新增score字段/方法:
	private int score;

	public int getScore() {
		return this.score;

	}

	public void setScore(int score) {
		if (score < 0 || score > 100) {
			throw new IllegalArgumentException("invalid score value");
		}
		this.score = score;
	}
}

// 阻止继承
// 正常情况下，只要某个class没有final修饰符，那么任何类都可以从该class继承。
// 从Java 15开始，允许使用sealed修饰class，并通过permits明确写出能够从该class继承的子类名称。
//public sealed class Shape permits Rect, Circle, Triangle {
//    ...
//}
//上述Shape类就是一个sealed类，它只允许指定的3个类继承它。如果写：
//public final class Rect extends Shape {...}
//是没问题的，因为Rect出现在Shape的permits列表中。但是，如果定义一个Ellipse就会报错：

//public final class Ellipse extends Shape {...}
// Compile error: class is not allowed to extend sealed class: Shape

//原因是Ellipse并未出现在Shape的permits列表中。这种sealed类主要用于一些框架，防止继承被滥用。
//sealed类在Java 15中目前是预览状态，要启用它，必须使用参数--enable-preview和--source 15。
class Studenta extends Persons {
	protected int score;

	public Studenta(String name, int age, int score) {
		super(name, age);
		this.score = score;
	}

	public int getScore() {
		return score;
	}
}

class PrimaryStudent extends Studenta {
	protected int grade;
	
	public PrimaryStudent(String name, int age, int score,int grade) {
		super(name, age, score);
	}
	public int getGrade() {
		return grade;
	}
}